import { ALL_END, initialState } from "./const/index";
import { getTextByCanvas } from "./utils/canvas2Text";
import { getWords } from "./utils/getStreamerWords";
import { findElementByTextDFS, findZhuboCardItemAndClick, getCurrentZhubo, getGameStatus, getHHmmss, sleep, str1HasStr2 } from "./utils/index";
import { appendDom, generateCateElementClassName, judgeLogin, sendLog } from "./utils/init/index";
import { getRightPankouWith } from "./utils/pay/queryPankouWithItem";
import { touzhuFunc, updateOrders } from "./utils/pay/util";

declare var _: any;

class MakeMoney {
  private state = initialState;
  constructor() {
    // 每 5s 获取关闭按钮，有的话关掉
    setInterval(() => {
      const closeBtn = document.getElementsByClassName("closeBtn")?.[0] as HTMLElement;
      closeBtn?.click();
    }, 5000);

    // 发送日志到node
    sendLog(this.state);

    appendDom({
      init: this.init,
      start: this.start,
      stopInterval: () => {
        this.state.clickPause = !this.state.clickPause;
        console.log("[zjymock:state]", this.state);
      },
      mockToggle: () => {
        this.state.isMock = !this.state.isMock;
        console.log("[zjymock:]已切换", this.state.isMock);
      },
      goMakeMoney: this.goMakeMoney,
      isMock: this.state.isMock
    });

    this.init();
  }


  async init() {
    let errorTime = 0;
    this.state = initialState;

    if (!judgeLogin(this.state.isMock)) {
      return;
    }

    console.log("[zjymock:init()]", "初始化 ");
    const isFind = findZhuboCardItemAndClick(this.state.zhuboming);
    if (!isFind) {
      this.state.findZhuBoTime++;
      if (this.state.findZhuBoTime > 60) {
        await sleep(3 * 60 * 1000);
        this.init();
        return;
      }
      console.log(
        "[zjymock:没找到主播]",
        this.state.zhuboming,
        `${this.state.initSleepTimeStamp}毫秒后再次获取主播节点`
      );
      await sleep(this.state.initSleepTimeStamp);
      this.init();
      return;
    }

    console.log("[zjymock:]", "5s后获取主客场名字、右侧投注div");
    await sleep(5 * 1000);

    const wrapperElement = document.getElementsByClassName("el-collapse")?.[0];
    const zhuName =
      (document.getElementsByClassName("info_team_name")?.[0] as HTMLElement)?.innerText;
    const keName =
      (document.getElementsByClassName("info_team_name")?.[1] as HTMLElement)?.innerText;

    // 去掉banner，浪费资源
    document.getElementsByClassName("banner_div")?.[0]?.remove?.();

    const chatRoomdom = document.getElementsByClassName("chat-room")?.[0] as HTMLElement;
    if (chatRoomdom) {
      chatRoomdom.style.display = "none";
    }
    if (wrapperElement && zhuName && keName) {
      this.state.zhuName = zhuName;
      this.state.keName = keName;
      // 生成盘口一级类的classname 的 maps
      // this.generateCateElementClassName();
      // 生成主播的一些常用的 文本 双飞 大2.5 这种
      this.genWords();

      console.log("[zjymock:30s后，再执行start]", getHHmmss());

      await sleep(2 * 1000);
      await this.start();
    } else {
      if (errorTime > 5) {
        return;
      }
      errorTime++;
      this.init();
    }
  }

  async start() {
    console.log("[zjymock:start, state:]", this.state);

    // 判断是否登录
    if (!judgeLogin(this.state.isMock) || this.state.clickPause) {
      return;
    }

    // 判断是否找得到主播
    if (!findZhuboCardItemAndClick(this.state.zhuboming)) {
      console.log(
        "[zjymock:]",
        `没找到主播吗，${this.state.cantFindZhuBoTs
        }ms再调用init,${getHHmmss()}`
      );
      await sleep(this.state.cantFindZhuBoTs);
      this.state.initSleepTimeStamp = this.state.cantFindZhuBoTs;
      this.init();
      return;
    }

    // 判断是否结束了
    const gameStatus = getGameStatus();
    if (gameStatus === ALL_END) {
      console.log(
        "[zjymock:]",
        `已经下播了，${this.state.cantFindZhuBoTs
        }ms再调用init,${getHHmmss()}`
      );
      await sleep(this.state.cantFindZhuBoTs);
      this.state.initSleepTimeStamp = this.state.cantFindZhuBoTs;
      this.init();
      return;
    }

    // 已经下单的缓存
    const lskey = this.state.zhuName + "VS" + this.state.keName;
    this.state.lskey = lskey;
    this.state.orderItems =
      JSON.parse(localStorage.getItem(lskey) || "[]") || [];
    console.log(
      "[zjymock:orderItems]",
      this.state.orderItems,
      "接下来获取 开始截图获取canvas"
    );

    // 开始下单
    const { textArr } = await getTextByCanvas();

    console.log(
      "[zjymock:]",
      `直接下单，下完单后直接执行start:${getHHmmss()}`
    );

    await this.goMakeMoney(textArr);
    console.log("30s后重新init");
    // zjytodo
    await sleep(this.state.cantFindZhuBoTs);
    // await sleep(30 * 1000);
    await this.init();
  }

  genWords() {
    const mapWords = getWords();
    // 这里需要将key 的主 客 处理成真实
    const handleWords: Record<string, string[]> = {};
    Object.keys(mapWords).forEach((key) => {
      let newText = key;
      if (newText.includes("主")) {
        newText = newText.replace("主队", this.state.zhuName?.replace(' ', ''));
      }
      if (newText.includes("客")) {
        console.log(key, "key");
        newText = newText.replace("客队", this.state.keName?.replace(' ', ''));
      }
      handleWords[newText] = mapWords[key];
    });
    this.state.zhuboMapWords = handleWords;
  }



  async goMakeMoney(texts: string[]) {
    console.log("[zjymock:texts]", texts);

    // 需要重新setclassname，classname会变
    const { maps, noReal2RealMaps, real2NoRealMaps } = generateCateElementClassName(this.init);

    this.state.cateElementClassNameMaps = maps;
    this.state.noReal2RealMaps = noReal2RealMaps;
    // 遍历所有二级类
    this.state.real2NoRealMaps = real2NoRealMaps;

    await sleep(3 * 1000);

    // [ { key: '大小', text: '大n球' } ]
    const results = getRightPankouWith({
      texts: texts,
      zhuboMapWords: this.state.zhuboMapWords,
      noReal2RealMaps: this.state.noReal2RealMaps,
      zhuName: this.state.zhuName,
      keName: this.state.keName
    });
    console.log("[zjymock:getRightPankouWith:results]", results);

    const logs = [];

    let i = 0;

    if (!getCurrentZhubo(this.state.zhuboming)) {
      return
    }

    while (i < results.length) {
      let result = results[i];

      const res = await this.goOrderOneItem(result);
      logs.push(res);


      updateOrders(this.state.orderItems);
      i += 1;
    }
    console.log(
      `[zjymock:makemoney结束,${getHHmmss()}，3分钟后再start]`,
      logs
    );
  }

  async goOrderOneItem(orderItem: { text: string, key: string, pay: number }) {
    const { text, key: pankouRealKey, pay } = orderItem;
    console.log({ orderItem });

    return new Promise(async (resolve) => {
      let lastNoRealKey = "";
      const noRealKeys = Object.keys(this.state.noReal2RealMaps);
      console.log({ noRealKeys, maps: this.state.noReal2RealMaps });

      for (let i = 0; i < noRealKeys.length; i++) {

        const noRealKey = noRealKeys[i];
        console.log({ pankouRealKey, noRealKey });

        // 因为盘口的文字容易变
        // 如果 这个noRealkey 能和 pankouRealKey 相似 ，就匹配
        // pankouRealKey : 上半场鲁森比洛克进球大小
        // noRealKey : 鲁森比洛克进球大小上半场
        const isSame =
          str1HasStr2(pankouRealKey, noRealKey) &&
          str1HasStr2(noRealKey, pankouRealKey);

        if (isSame) {
          // 如果找到了就结束
          lastNoRealKey = noRealKey;
          break;
        }
      }


      const realKey = (this.state.noReal2RealMaps as any)[lastNoRealKey];
      const cn = (this.state.cateElementClassNameMaps as any)[realKey];
      console.log({ realKey, lastNoRealKey });
      const cateElement = document.getElementsByClassName(cn)?.[0];
      const pankouResult = await findElementByTextDFS(cateElement, text);
      console.log({ cateElement, text });
      console.log('test 91', pankouResult);

      const isOrdered = this.state.orderItems.find((item: any) => {
        if (item?.text === text && realKey?.includes("比分")) {
          return true;
        } else {
          return _.isEqual(item, orderItem);
        }
      });
      if (isOrdered) {
        resolve({
          text,
          lastNoRealKey,
          pankouRealKey,
          pay,
          realKey,
          log: "[zjymock:]这个盘口已经下过单了",
        });
      } else {
        if (pankouResult) {
          const res = await this.inputValAndPay(pankouResult as HTMLElement, pay);
          if (res) {
            // 说明下单成功
            this.state.orderItems.push(orderItem as never);
            // { 20240824横滨-xx: [ { ...orderItem } ] }
            const ordersStr = localStorage.getItem(this.state.lskey);
            const os = JSON.parse(ordersStr || "[]");
            os.push(orderItem);
            localStorage.setItem(this.state.lskey, JSON.stringify(os));
            resolve({
              text,
              lastNoRealKey,
              pankouRealKey,
              pay,
              realKey,
              log: `[zjymock:下单成功], ${text}, ${res}`,
            });
          } else {
            // 下单失败，可以再下一次 start方法中下单
            resolve({
              text,
              lastNoRealKey,
              pankouRealKey,
              pay,
              realKey,
              log: `[zjymock:盘口应该是没了或者变化了]`,
            });
          }
        } else {
          console.log('test 90');
          resolve({
            text,
            lastNoRealKey,
            pankouRealKey,
            pay,
            realKey,
            log: `[zjymock:盘口应该是没了]`,
          });
        }
      }
    });
  }

  // 输入金额，点击投注
  inputValAndPay(pankouResult: HTMLElement, pay: string | number) {
    return new Promise(async (resolve) => {
      // 点击投注
      const touzhuCaidan = document
        .getElementsByClassName("el-tabs__header is-top")?.[0]
        .getElementsByClassName("el-tabs__item is-top")?.[1] as HTMLElement;
      // 点击展开
      const zhankaiNode = document.getElementsByClassName(
        "collapse_btn ratate_180"
      )?.[0] as HTMLElement;
      if (touzhuCaidan) {
        touzhuCaidan.click();
      }
      if (zhankaiNode) {
        zhankaiNode.click();
      }

      // mock一下
      // resolve('touzhuSuccessDom');
      // zjytodo
      // return
      console.log("[zjymock:]", pankouResult);
      if (!pankouResult) {
        resolve(false);
        return;
      }

      //
      if (this.state.isMock) {
        resolve("touzhuSuccessDom");
        return;
      }
      pankouResult?.parentElement?.parentElement?.parentElement?.click();
      await sleep(1800)

      // 实时获取 弹出框
      const dialogWarpper = document.getElementsByClassName("bet_dialog")?.[0];
      console.log({ dialogWarpper });

      const inputDom =
        dialogWarpper.getElementsByClassName("el-input__inner")?.[0] as HTMLInputElement;
      // 固定全部投 10 块钱 zjytodo
      inputDom.value = String(pay);
      inputDom.dispatchEvent(new Event("input"));

      // 判断是否打开了dialog
      const touzhuElement = findElementByTextDFS(
        dialogWarpper,
        "投注"
      ) as HTMLDivElement;
      if (touzhuElement) {
        touzhuElement?.click();
      }
      const touzhuRes = await touzhuFunc(dialogWarpper as HTMLElement);
      if (touzhuRes === "投注成功") {
        console.log("[zjymock:查找成功]", touzhuRes);
        this.state.touzhuTime = 0;
        // 关闭蒙层
        (document.getElementsByClassName("bet_dialog_overlay")?.[0] as HTMLElement)?.click();

        // 投注完 5s 后再来投注下一单
        await sleep(5 * 1000);

        resolve(touzhuRes);
      } else {
        this.state.touzhuTime++;
        if (this.state.touzhuTime < 5) {
          (document.getElementsByClassName("bet_dialog_overlay")?.[0] as HTMLElement)?.click();
          await sleep(2000);
          console.log(
            `投注失败：需要再次进入，这是第${this.state.touzhuTime}次调用 inputValAndPay 方法`
          );
          const res = await this.inputValAndPay(pankouResult, pay);
          resolve(res);
          return;
        } else {
          (document.getElementsByClassName("bet_dialog_overlay")?.[0] as HTMLDivElement)?.click();
          resolve(false);
        }
      }
    });
  }


}

(function () {
  // 初始化一下公共三个忽远忽近
  const money = new MakeMoney();
  console.log("[zjymock:]", money);
})();
